using Godot;
using RPG01.Scripts.SateMachine;
namespace RPG01.Scripts.Character.Player;

public partial class Player : CharacterBody3D
{
	
	[Export] private float moveSpeed = 5.0f;

	[Export] private float jumpHeight = 2.25f;
	[Export] private float jumpTimeToPeak = 0.4f;
	[Export] private float JumpTimeToDescent = 0.3f;
	
	private float jumpVelocity;
	private float jumpGravity;
	private float fallGravity;

	private AnimatedSprite3D animated;
	private StateMachine stateMachine;

	public void PlayAnimation(string name)
	{
		animated.Play(name);
	}

	public Vector2 GetMoveInput()
	{
		return Input.GetVector("move_left", "move_right", "move_up", "move_down");
	}

	public override void _Ready()
	{
		jumpVelocity = ((jumpHeight * 2.0f) / jumpTimeToPeak) * -1.0f;
		jumpGravity = (jumpHeight * -2.0f) / (jumpTimeToPeak * jumpTimeToPeak) * -1.0f;
		fallGravity = jumpHeight * -2.0f / (JumpTimeToDescent * JumpTimeToDescent) * -1.0f;
		// https://youtu.be/IOe1aGY6hXA?feature=shared

		animated = GetNode<AnimatedSprite3D>("AnimatedSprite3D");
		stateMachine = GetNode<StateMachine>("StateMachine");
		InitStateMachine();
	}

	private void InitStateMachine()
	{
		stateMachine.ClearStateAll();

		var idleState = new PlayerIdleState(this, stateMachine);
		stateMachine.AddState(idleState);

		var moveState = new PlayerMoveState(this, stateMachine);
		stateMachine.AddState(moveState);
		
		var jumpState = new PlayerJumpState(this, stateMachine);
		stateMachine.AddState(jumpState);
		
		stateMachine.SwitchState<PlayerIdleState>();
	}

	public override void _PhysicsProcess(double delta)
	{
		
		JumpLogic((float)delta);
		// MoveLogic((float)delta);
		//
		//
		MoveAndSlide();
	}


	public void AddMovement(Vector2 movement)
	{
		Velocity = new Vector3(movement.X, Velocity.Y, movement.Y) * moveSpeed;
	}

	public void Jump()
	{
		var velocity = Velocity;
		velocity.Y = -jumpVelocity;
		Velocity = velocity;
	}

	private void MoveLogic(float delta)
	{
		Vector2 vel2d = new Vector2(Velocity.X, Velocity.Z);
		Vector2 movement_input = Input.GetVector("move_left", "move_right", "move_up", "move_down");
		
		if (movement_input != Vector2.Zero)
		{
			vel2d += movement_input * moveSpeed * delta * 10.0f;
			vel2d = vel2d.LimitLength(moveSpeed);
		}
		else
		{
			vel2d = vel2d.MoveToward(Vector2.Zero, moveSpeed * 10.0f * delta);
		}
		Velocity = new Vector3(vel2d.X, Velocity.Y, vel2d.Y);
	}

	private void JumpLogic(float delta)
	{
	
		Vector3 velocity = Velocity;
		// if (Input.IsActionJustPressed("jump") && IsOnFloor())
		// {
		// 	velocity.Y = -jumpVelocity;
		// }
		
		
		float gravity = velocity.Y > 0.0f ? jumpGravity : fallGravity;
		velocity.Y -= gravity * delta;
		Velocity = velocity;
	}
}
